/*
 * Copyright (c) 2011-2012, Two Trolls Entertainment
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of the Rhenium nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Two Trolls Entertainment BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_opengl.h>
#include <iostream>
#include "utils.h"

Utils::Timer::Timer()
{
    startTime = pauseTime = 0;
    bPaused = bStarted = false;
}

void Utils::Timer::start()
{
    startTime = SDL_GetTicks();
    bStarted = true;
    bPaused = false;
}

void Utils::Timer::stop()
{
    bStarted = bPaused = false;
}

void Utils::Timer::pause()
{
    if (bStarted)
    {
        bPaused = !bPaused;
        if (bPaused)
            pauseTime = SDL_GetTicks() - startTime;
        else
        {
            startTime = SDL_GetTicks() - pauseTime;
            pauseTime = 0;
        }
    }
}

int Utils::Timer::getTicks()
{
    if (bStarted)
    {
        if (bPaused)
        {
            return pauseTime;
        }
        else
        {
            return SDL_GetTicks() - startTime;
        }
    }

    return -1;
}

bool Utils::Timer::isStarted()
{
    return bStarted;
}

bool Utils::Timer::isPaused()
{
    return bPaused;
}

Utils::InputHandler::InputHandler(int nInputType, int nInputID)
{
    inputType = nInputType;
    inputID = nInputID;


    for (int i=0; i < 8; i++)
        bButtonsHeld[i] = false;
}

void Utils::InputHandler::tick(SDL_Event event)
{
    if (inputType == INPUT_KEYBOARD && (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) && inputID == event.key.which) //Keyboard
        handleKeyboard(event);

    else if (inputType == INPUT_MOUSE) //Mouse: TODO
    {}

    else if (inputType == INPUT_JOYSTICK && (event.type == SDL_JOYAXISMOTION || event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP) && inputID == event.jaxis.which) //Joystick
        handleJoystick(event);
}

void Utils::InputHandler::handleKeyboard(SDL_Event event)
{
    switch (event.type)
    {
        case SDL_KEYDOWN:
            switch (event.key.keysym.sym)
            {
                case SDLK_w: bButtonsHeld[UP] = true; break;
                case SDLK_a: bButtonsHeld[LEFT] = true; break;
                case SDLK_s: bButtonsHeld[DOWN] = true; break;
                case SDLK_d: bButtonsHeld[RIGHT] = true; break;
                default: break;
            }
        break;

        case SDL_KEYUP:
        switch (event.key.keysym.sym)
            {
                case SDLK_w: bButtonsHeld[UP] = false; break;
                case SDLK_a: bButtonsHeld[LEFT] = false; break;
                case SDLK_s: bButtonsHeld[DOWN] = false; break;
                case SDLK_d: bButtonsHeld[RIGHT] = false; break;
                default: break;
            }
        break;

    }
}

void Utils::InputHandler::handleJoystick(SDL_Event event)
{
    if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP)
    {
        int button = event.jbutton.button;
        bool buttonIsDown = (event.type == SDL_JOYBUTTONDOWN);

        switch (button)
        {
            case 1: bButtonsHeld[FIRE] = buttonIsDown; break;
            default: break;
        }
    }
    else
    {
        if (event.jaxis.axis == 0) //X axis
        {
            if (event.jaxis.value > -2000 && event.jaxis.value < 2000) //Input padding
            {
                bButtonsHeld[RIGHT] = bButtonsHeld[LEFT] = false;
            }
            else
            {
                if (event.jaxis.value < 0) //Left held
                {
                    bButtonsHeld[RIGHT] = false;
                    bButtonsHeld[LEFT] = true;
                }
                else
                {
                    bButtonsHeld[RIGHT] = true;
                    bButtonsHeld[LEFT] = false;
                }

            }
        }
        else if (event.jaxis.axis == 1) //Y axis
        {
            if (event.jaxis.value > -2000 && event.jaxis.value < 2000) //Input padding
            {
                bButtonsHeld[UP] = bButtonsHeld[DOWN] = false;
            }
            else
            {
                if (event.jaxis.value < 0) //Up held
                {
                    bButtonsHeld[DOWN] = false;
                    bButtonsHeld[UP] = true;
                }
                else
                {
                    bButtonsHeld[DOWN] = true;
                    bButtonsHeld[UP] = false;
                }

            }
        }
    }
}

bool Utils::InputHandler::upHeld()
{
    return bButtonsHeld[UP];
}

bool Utils::InputHandler::downHeld()
{
    return bButtonsHeld[DOWN];
}

bool Utils::InputHandler::leftHeld()
{
    return bButtonsHeld[LEFT];
}

bool Utils::InputHandler::rightHeld()
{
    return bButtonsHeld[RIGHT];
}

bool Utils::InputHandler::fireHeld()
{
    return bButtonsHeld[FIRE];
}

bool Utils::InputHandler::fireAltHeld()
{
    return bButtonsHeld[FIRE_ALT];
}

bool Utils::InputHandler::shieldHeld()
{
    return bButtonsHeld[SHIELD];
}

bool Utils::InputHandler::startHeld()
{
    return bButtonsHeld[START];
}

void Utils::FileManager::loadTextureFromPNG(GLuint *texture, const char *filePath)
{
    SDL_Surface *surface = IMG_Load(filePath);
    glGenTextures(1, texture);
    glBindTexture(GL_TEXTURE_2D, *texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);

    if (surface)
        SDL_FreeSurface(surface);
}
